package com.gopay.scheduler.job;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.cust.SMSResultConstants;
import com.gopay.common.constants.cust.SMSType;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.util.DateUtils;
import com.gopay.remote.user.UserSmsRemoteService;
import com.gopay.remote.vo.UserSendSmsReq;
import com.gopay.scheduler.GopayBaseJob;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.text.DecimalFormat;

/**
 * 对一定时间段内所有银行订单的状态为(处理中，成功，失败)的订单占比超出预警值的进行短信通知
 * 预警值设置在cron.properties文件中
 * @author LEI XIAOBAO
 * @date 2016年2月18日
 */
public class BankOrderRateOverageingWarningJob extends GopayBaseJob {

	@Value("#{webProperties['autoSettle.underwayStatus']}")
	private String underwayStatus;
	
	@Value("#{webProperties['autoSettle.succStatus']}")
	private String succStatus;
	
	@Value("#{webProperties['autoSettle.failStatus']}")
	private String failStatus;
	
	@Value("#{webProperties['autoSettle.warningTime']}")
	private String warningTime;
	
	@Value("#{webProperties['autoSettle.underwayRate']}")
	private BigDecimal underwayRate;
	
	@Value("#{webProperties['autoSettle.failRate']}")
	private BigDecimal failRate;
	
	@Value("#{webProperties['autoSettle.succRate']}")
	private BigDecimal succRate;
	
	@Value("#{webProperties['autoSettle.recvMobile']}")
	private String recvMobile;
	
	@Value("#{webProperties['autoSettle.bcdlBank']}")
	private String bcdlBank;
	
	@Value("#{webProperties['autoSettleRunEnvironment']}")
	private String autoSettleRunEnvironment;
	
	private Logger logger = LoggerFactory.getLogger(BankOrderRateOverageingWarningJob.class);
	
	@Resource(name = "commonQueryDAO")
    private CommonQueryDAO commonQueryDAO;
	
	@Resource(name = "userSmsRemoteClient")
	private UserSmsRemoteService userSmsRemoteClient;
    
	@Override
	protected void doJobInternal() {
		logger.error("===================BankOrderRateOverageingWarningJob Begin================");
		List<String> mobiles = new ArrayList<String>();
		List<String> bankCodes = new ArrayList<String>();
		String[] recvMobiles = recvMobile.split(",");
		String[] bcdlBanks = bcdlBank.split(",");
		//预警短信接收人
		for( String mob : recvMobiles ){
			mobiles.add(mob);
		}
		//银企直连银行
		for( String bank : bcdlBanks ){
			bankCodes.add(bank);
		}
		
		int warningDate = Integer.parseInt(warningTime);
		Date currDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currDate);
        calendar.add(Calendar.MINUTE, -warningDate);
        String startDay = DateUtils.format(calendar.getTime(), "yyyyMMddHHmmss");//开始时间
        
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(currDate);
        calendar2.add(Calendar.MINUTE, -2);
        String today = DateUtils.format(calendar2.getTime(), "yyyyMMddHHmmss");//当前时间
        logger.error("查询开始日期："+startDay+"|查询结束日期："+today);
        for( String bankCode : bankCodes ){
        	String sendContent = "";
        	Map<String, Object> bankOrderData = getBankOrderStatisticsData(startDay, today, bankCode);
        	logger.error("bankOrderData Map："+ToStringBuilder.reflectionToString(bankOrderData,ToStringStyle.DEFAULT_STYLE));
        	//符合时间段中的总订单数
    		int totalOrderCount = Integer.parseInt(bankOrderData.get("totalCount").toString());
    		logger.error("查询总订单数为: "+totalOrderCount);
    		int underwayCount = Integer.parseInt(bankOrderData.get("underwayCount").toString());
    		logger.error("查询处理中订单数为: "+underwayCount);
    		//进行中订单预警值
    		if( underwayCount > 0 ){
    			BigDecimal uRate = new BigDecimal(bankOrderData.get("underwayRate").toString());
    			if( uRate.compareTo(underwayRate) >= 0 && !StringUtils.equals(bankCode, "CMB")){
        			DecimalFormat df = new DecimalFormat("0.00");//格式化小数，不足的补0
          			String uRateFormt = df.format(uRate);
        			logger.error("处理中订单占总订单预警比率: "+uRateFormt);
    				sendContent += bankCode+"银行订单处理中的订单数为"+underwayCount+"占比为："+uRateFormt+"%";;
    			}
//    			logger.error("处理中订单占比: "+underwayRate);

    		}
    		
    		//成功订单预警值
    		int succCount = Integer.parseInt(bankOrderData.get("succCount").toString());
    		logger.error("查询成功订单数为: "+succCount);
    		if( succCount > 0 ){
    			BigDecimal sRate = new BigDecimal(bankOrderData.get("succRate").toString());
    			logger.error("成功订单占比: "+succRate);
    			if( sRate.compareTo(succRate) >= 0){
        			DecimalFormat df = new DecimalFormat("0.00");//格式化小数，不足的补0
          			String sRateFormt = df.format(sRate);
        			logger.error("处理中订单占总订单预警比率: "+sRateFormt);
      				if( sendContent.equals("") ){
    					sendContent += bankCode+"银行订单成功的订单数为"+succCount+"占比为："+sRateFormt+"%";
    				}else{
    					sendContent += "，银行订单成功的订单数为"+succCount+"占比为："+sRateFormt+"%";
    				}
    			}
    		}
    		
    		//失败订单预警值
    		int failCount = Integer.parseInt(bankOrderData.get("failCount").toString());
    		logger.error("查询失败订单数为: "+failCount);
    		if( failCount > 0 ){
    			BigDecimal fRate = new BigDecimal(bankOrderData.get("failRate").toString());
    			logger.error("失败订单占比: "+failRate);
    			if( fRate.compareTo(failRate) >= 0 ){
        			DecimalFormat df = new DecimalFormat("0.00");//格式化小数，不足的补0
          			String fRateFormt = df.format(fRate);
        			logger.error("处理中订单占总订单预警比率: "+fRateFormt);
    				if( sendContent.equals("") ){
    					sendContent += bankCode+"银行订单失败的订单数为"+failCount+"占比为："+fRateFormt+"%";
    				}else{
    					sendContent += "，银行订单失败的订单数为"+failCount+"占比为："+fRateFormt+"%";
    				}
    			}
    		}
    		if( mobiles.size() > 0 && !sendContent.equals("") ){
    			sendContent += "，总订单数为"+totalOrderCount+"超过预警值，请悉知。";
    			String scontent = "【开发环境】"+sendContent;
    			if( autoSettleRunEnvironment.equals("test") ){
    				scontent = "【测试环境】"+sendContent;
    			}else if( autoSettleRunEnvironment.equals("gray") ){
    				scontent = "【灰度环境】"+sendContent;
    			}else if( autoSettleRunEnvironment.equals("prod") ){
    				scontent = "【生产环境】"+sendContent;
    			}else if( autoSettleRunEnvironment.equals("local") ){
    				scontent = "【本地环境】"+sendContent;
    			}else if( autoSettleRunEnvironment.equals("bank") ){
    				scontent = "【银行环境】"+sendContent;
    			}
				sendSms(mobiles, scontent);
			}
		}
        logger.error("===================BankOrderRateOverageingWarningJob End================");
	}
	
	/**
	 * 获取银行订单统计数据
	 * @param startDay
	 * @param today
	 * @param bankCode
	 * @return
	 */
	private Map<String, Object> getBankOrderStatisticsData(String startDay, String today, String bankCode){
		Map<String, Object> retMap = new HashMap<String, Object>();
		String[] underwayStatusArray = underwayStatus.split(",");
		String[] succStatusArray = succStatus.split(",");
		String[] failStatusArray = failStatus.split(",");
		StringBuffer sql = new StringBuffer();
		sql.append("select count(*) totalCount,");
		sql.append("count(CASE WHEN m.order_status in ('"+StringUtils.join(underwayStatusArray,"','")+"') THEN m.order_status ELSE NULL END) underwayCount, ");
		sql.append("count(CASE WHEN m.order_status in ('"+StringUtils.join(failStatusArray,"','")+"') THEN m.order_status ELSE NULL END) failCount, ");
		sql.append("decode(count(*),0,0,");
		sql.append("count(CASE WHEN m.order_status in ('"+StringUtils.join(underwayStatusArray,"','")+"') THEN m.order_status ELSE NULL END)/count(*)");
		sql.append("*100) underwayRate,");
		sql.append("decode(count(*),0,0,");
		sql.append("count(CASE WHEN m.order_status in ('"+StringUtils.join(failStatusArray,"','")+"') THEN m.order_status ELSE NULL END)/count(*)");
		sql.append("*100) failRate,");
		sql.append("count(CASE WHEN m.order_status in ('"+StringUtils.join(succStatusArray,"','")+"') THEN m.order_status ELSE NULL END) succCount, ");
		sql.append("decode(count(*),0,0,");
		sql.append("count(CASE WHEN m.order_status in ('"+StringUtils.join(succStatusArray,"','")+"') THEN m.order_status ELSE NULL END)/count(*)");
		sql.append("*100) succRate");
		sql.append(" from bis_bank_main_order m where 1=1");
		sql.append(" AND m.SEND_BANK_TM<to_timestamp(:dateEnd, 'yyyymmddHH24miss') ");
		sql.append(" AND m.SEND_BANK_TM>=to_timestamp(:dateBegin, 'yyyymmddHH24miss') ");
		sql.append(" AND m.BANK_BIZ_PROD_CODE=:bankBizProdCode");
		sql.append(" AND m.GOPAY_BANK_CODE=:bankCode");
		
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("dateBegin", startDay);
		param.put("dateEnd", today);
		param.put("bankBizProdCode", BisBankBusinessProd._09.value);
		param.put("bankCode", bankCode);
		logger.error("get total orderCount："+sql.toString());
		logger.error("查询条件： bankBizProdCode="+BisBankBusinessProd._09+"|bankCode="+bankCode+"|dateBegin="+startDay+"|dateEnd="+today);
		List<Object[]> rsList = commonQueryDAO.findBySql(sql.toString(), param);
		logger.error("查询rsList："+rsList.size());
		if( rsList != null && rsList.size() > 0 ){
			for (Object[] bankOrder : rsList) {
				retMap.put("totalCount", bankOrder[0]);
				retMap.put("underwayCount", bankOrder[1]);
				retMap.put("failCount", bankOrder[2]);
				retMap.put("underwayRate", bankOrder[3]);
				retMap.put("failRate", bankOrder[4]);
				retMap.put("succCount", bankOrder[5]);
				retMap.put("succRate", bankOrder[6]);
			}
		}
		logger.error("查询retMap: "+retMap.size());
		return retMap;
	}
	
	/**
	 * 短信发送
	 * @param mobiles
	 * @param sendContent
	 */
	private void sendSms(List<String> mobiles, String sendContent) {
		for( String mob : mobiles ){
			UserSendSmsReq userSmsReq = new UserSendSmsReq();
			userSmsReq.setMobileNo(mob);
			userSmsReq.setContent(sendContent);
			userSmsReq.setSmsMaxCount(0);
			userSmsReq.setSmsType(SMSType.OTHER_SMS);
			logger.error("mob="+mob+"|sendContent="+sendContent+"|");
			int result = userSmsRemoteClient.sendMobileSMS(userSmsReq);
			if( SMSResultConstants.SEND_RESULT_FAIL == result ){
				logger.error("send sms error!"+result);
			}else if( SMSResultConstants.SEND_RESULT_EXCEED == result ){
				logger.error("send sms error!"+result);
			}else{
				logger.info("send sms success!"+result);
			}
		}
	}
}
